<?php

namespace App\Http\Controllers\Backstage\System;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Validation\Rule;
use App\Services\UserGroupService;
use App\Services\CityService;
use App\Services\UserService;
use App\Services\RoleService;
use App\BaseDictionary;
use App\UserGroup;
use App\User;
use App\Lib\Auth\UserProfileHelper;

class UserController extends Controller
{
    private $userGroupService = null;
    private $userProfileHelper = null;
    private $userService = null;
    private $roleService = null;
    private $cityService = null;

    public function __construct(UserGroupService $userGroupService,
        RoleService $roleService,
        UserService $userService,
        CityService $cityService,
        UserProfileHelper $userProfileHelper)
    {
        $this->userGroupService = $userGroupService;
        $this->userProfileHelper = $userProfileHelper;
        $this->cityService = $cityService;
        $this->userService = $userService;
        $this->roleService = $roleService;
    }

    public function index()
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];
            $currentUserGroup = $this->userGroupService->getCurrentUserGroup($currentUserGroupId);

            $roles = $this->roleService->getGroupRoles($currentUserGroupId);

            if ($currentUserGroup->isExternalEnterprise()) {
                return view('backstage.system.user.user_external', [
                    'groupId' => $currentUserGroupId,
                    'roles' => $roles
                ]);
            } else if ($currentUserGroup->isInternalOrganization()) {
                return view('backstage.system.user.user_organiztion', [
                    'roles' => $roles
                ]);
            }
        } else {
            return redirect('/backstage/current-org')->withErrors([
                'error_text' => '未设置当前用户默认组织，因此无法查看组织下用户',
            ]);;
        }
    }

    public function queryByDept(Request $request)
    {
        $input = $request->all();

        $this->validateCanQuery($input);

        return $this->userService->getUsers($input);
    }

    public function queryUsers(Request $request)
    {
        $input = $request->all();

        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

        $input['deptId'] = $currentUserGroupId;

        return $this->userService->getUsers($input);
    }

    public function toSelectUser($groupId)
    {
        return view('backstage.system.user.select_user', [
            'groupId' => $groupId
        ]);
    }

    public function checkUserByMobile(Request $request)
    {
        $input = $request->all();

        $this->validateUserMobileQuery($input);

        $user = $this->userService->checkUserByMobile($input['mobile']);

        return isset($user) ? response()->json([
            'Success' => true,
            'ErrorCode' => $user->isActive()?($user->isSuper()?2:0):1,
            'Message' => $user->isActive()?
                ($user->isSuper()?'该手机用户是系统超级用户':''):'该手机用户未激活或者已被禁用',
            'ResultData' => [
                'user' => $user->isActive() && !$user->isSuper() ? [
                    'user_id' => $user->id,
                    'mobile' => $user->mobile,
                    'nick_name' => $user->nick_name,
                ] : []
            ]
        ]) : response()->json([
            'Success' => false,
            'ErrorCode' => 3,
            'Message' => '无法找到该手机对应用户'
        ]);
    }

    public function toCreateNewUser(Request $request)
    {
        $input = $request->all();

        $this->validateUserMobileQuery($input);

        $user = $this->userService->checkUserByMobile($input['mobile']);

        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();
        $roles = $this->roleService->getGroupRoles($managedGroupsInfo['currentUserGroupId']);

        if (isset($user)) {
            return view('backstage.system.user.select_exists_user', [
                'roles' => $roles,
                'groupId' => $input['groupId'],
                'user' => $user,
            ]);
        } else {
            return view('backstage.system.user.create_user', [
                'roles' => $roles,
                'mobile' => $input['mobile'],
                'groupId' => $input['groupId'],
            ]);
        }
    }

    public function getRegisterVerifyCode(Request $request)
    {
        $input = $request->all();

        $this->validateWhenSendVerifyCode($input);

        $this->userService->sendRegisterVerifyCode($input['mobile']);

        return response()->json([
            'Success' => true,
            'ErrorCode' => 0,
            'Message' => '发送验证码成功'
        ]);
    }

    public function toSaveNewUser(Request $request)
    {
        $input = $request->all();

        $this->validateWhenSaveNewUser($input);

        $this->userService->saveNewUser($input, $input['group_id'], explode(',', $input['roleIds']));

        return response()->json([
            'Success' => true,
            'ErrorCode' => 0,
            'Message' => '新建用户成功'
        ]);
    }

    public function modifyUser($userId)
    {
        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

        if (!empty($managedGroupsInfo)) {
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];
            $currentUserGroup = $this->userGroupService->getCurrentUserGroup($currentUserGroupId);

            $user = User::findOrFail($userId);
            if ($currentUserGroup->isExternalEnterprise()) {
                return view('backstage.system.user.modify_user', [
                    'enableParentOrg' => false,
                    'currentUserGroup' => $currentUserGroup,
                    'user' => $user
                ]);
            } else if ($currentUserGroup->isInternalOrganization()) {
                $userGroups = $user->userGroups;
                $currentGroup = null;
                foreach ($userGroups as $group) {
                    if ($group->coreOrganization()->id == $currentUserGroupId) {
                        $currentGroup = $group;
                        break;
                    }
                }
                return view('backstage.system.user.modify_user', [
                    'enableParentOrg' => true,
                    'groups' => $managedGroupsInfo['managedGroups'],
                    'currentUserGroup' => $currentGroup,
                    'user' => $user
                ]);
            }
        } else {
            return redirect('/backstage/current-org')->withErrors([
                'error_text' => '未设置当前用户默认组织，因此无法修改组织下用户',
            ]);;
        }
    }

    public function getModifyVerifyCode(Request $request)
    {
        $input = $request->all();

        $this->validateWhenSendVerifyCodeOnEdit($input);

        $this->userService->sendModifyVerifyCode($input['mobile']);

        return response()->json([
            'Success' => true,
            'ErrorCode' => 0,
            'Message' => '发送验证码成功'
        ]);
    }

    public function toSaveUpdateUser(Request $request)
    {
        $input = $request->all();

        $this->validateWhenSaveUpdateUser($input);

        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();
        $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];
        $currentUserGroup = $this->userGroupService->getCurrentUserGroup($currentUserGroupId);

        if ($currentUserGroup->isExternalEnterprise()) {
            $this->userService->saveUpdateUser($input, $currentUserGroupId);
        } else if ($currentUserGroup->isInternalOrganization()) {
            $this->userService->saveUpdateUser($input, $input['group_id']);
        }

        return response()->json([
            'Success' => true,
            'ErrorCode' => 0,
            'Message' => '修改用户成功'
        ]);
    }

    public function toRemoveFromGroup(Request $request)
    {
        $input = $request->all();

        $this->validateCanRemove($input);

        $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();
        $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

        $this->userService->removeUserFromCurrent($input['id'], $currentUserGroupId);

        return response()->json([
            'Success' => true,
            'ErrorCode' => 0,
            'Message' => '移除用户成功',
        ]);
    }

    private function validateCanRemove(Array $input)
    {
        return Validator::make($input, [
            'id' => 'required|exists:users,id',
        ], [
            'id.required' => '必须输入用户ID',
            'id.exists' => '传入的用户ID不存在',
        ])->after(function ($validator) use($input) {
            $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

            if ($this->userService->determineTheManagerIsCurrentUser($input['id'], $currentUserGroupId)) {
                $validator->errors()->add('id', '该用户是该组织的负责人之一，不可从该组织移除');
            }
        })->validate();
    }

    public function toAddUserToCurrent(Request $request)
    {
        $input = $request->all();

        $this->validateWhenAddUserToCurrent($input);

        $user = $this->userService->addUserToCurrentGroup($input['id'], $input['groupId'], explode(',', $input['roleIds']));

        return response()->json([
            'Success' => true,
            'ErrorCode' => 0,
            'Message' => '添加用户成功'
        ]);
    }

    private function validateWhenAddUserToCurrent(Array $input)
    {
        return Validator::make($input, [
            'id' => 'required|exists:users,id',
            'groupId' => 'required|exists:user_groups,id',
        ], [
            'id.required' => '必须输入用户ID',
            'id.exists' => '传入的用户ID不存在',
            'groupId.required' => '必须传入用户组ID',
            'groupId.exists' => '传入的用户组不存在',
        ])->after(function ($validator) use($input) {
            if ($this->userService->isCurrentUserInGroup($input['id'], $input['groupId'])) {
                $validator->errors()->add('id', '该用户已经属于该组织');
            }

            $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();
            $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

            $roles = $input['roleIds'];
            if (!empty($roles)) {
                $illegalRoles = $this->roleService->getGroupRoles($currentUserGroupId);

                $isRoleIllegal = true;
                $roleIds = explode(',', $roles);
                foreach ($roleIds as $roleId) {
                    if (!empty($roleId)) {
                        $isRoleIllegal = $isRoleIllegal && in_array($roleId, $illegalRoles->pluck('id')->toArray());
                    }
                }

                if (!$isRoleIllegal) {
                    $validator->errors()->add('role.illegal', '传入的用户角色不合法');
                }
            } else {
                $validator->errors()->add('role.required', '需要至少指定一个角色');
            }
        })->validate();
    }

    private function validateWhenSaveUpdateUser(Array $input)
    {
        return Validator::make($input, [
            'mobile' => [
                'required',
                'max:20',
                Rule::unique('users')->where(function ($query) use($input) {
                    $query->where('mobile', $input['mobile'])->where('id', '<>', $input['id']);
                })
            ],
            'nick_name' => 'max:20',
            'password' => 'max:20',
            'email' => [
                Rule::unique('users')->where(function ($query) use($input) {
                    if (!empty($input['email'])) {
                        $query->where('email', $input['email'])->where('id', '<>', $input['id']);
                    } else {
                        $query->where('email', '#');
                    }
                })
            ],
            'group_id' => 'required|exists:user_groups,id',
        ], [
            'mobile.required' => '没有输入手机号',
            'mobile.max' => '手机号长度不可超过:max',
            'mobile.unique' => '该手机号已被其它注册',
            'nick_name.max' => '用户昵称长度不可超过:max',
            'password.max' => '密码过长，不可超过:max',
            'email.unique' => '邮箱必须唯一',
            'group_id.required' => '必须传入用户组ID',
            'group_id.exists' => '传入的用户组不存在',
        ])->after(function ($validator) use($input) {
            if ($input['password'] !== $input['password_again']) {
                $validator->errors()->add('password_again', '两次输入密码不一致');
            }
            if ($this->userService->isModifyVerifyCodeExpired($input['mobile'])) {
                $validator->errors()->add('mobile.verifyCodeExpired', '验证码过期');
            }
            if (!$this->userService->isModifyVerifyCodeValid($input['mobile'], $input['verifyCode'])) {
                $validator->errors()->add('mobile.verifyCodeInvalid', '验证码不正确');
            }
            $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

            if (!empty($managedGroupsInfo)) {
                $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

                if (isset($input['group_id'])) {
                    $group = UserGroup::findOrFail($input['group_id']);
                    if ($group->coreOrganization()->id != $currentUserGroupId) {
                        $validator->errors()->add('group.illegal', '传入的用户组不合法');
                    }
                } else {
                    $validator->errors()->add('group.required', '用户没有所在用户组(部门或外部合作伙伴)信息');
                }
            } else {
                $validator->errors()->add('curgroup.required', '当前操作用户没有所在用户组(部门或外部合作伙伴)信息');
            }
        })->validate();
    }

    private function validateWhenSaveNewUser(Array $input)
    {
        return Validator::make($input, [
            'mobile' => 'required|max:20|unique:users,mobile',
            'name' => 'required|max:20|unique:users,name',
            'nick_name' => 'max:20',
            'password' => 'max:20|required',
            'email' => [
                Rule::unique('users')->where(function ($query) use($input) {
                    if (!empty($input['email'])) {
                        $query->where('email', $input['email']);
                    } else {
                        $query->where('email', '#');
                    }
                })
            ],
            'group_id' => 'required|exists:user_groups,id',
        ], [
            'mobile.required' => '没有输入手机号',
            'mobile.max' => '手机号长度不可超过:max',
            'mobile.unique' => '该手机号已被注册',
            'name.required' => '没有输入用户登录名',
            'name.max' => '用户登录名长度不可超过:max',
            'name.unique' => '该用户登录名已被注册',
            'nick_name.max' => '用户昵称长度不可超过:max',
            'password.max' => '密码过长，不可超过:max',
            'password.required' => '密码不可为空',
            'email.unique' => '邮箱必须唯一',
            'group_id.required' => '必须传入用户组ID',
            'group_id.exists' => '传入的用户组不存在',
        ])->after(function ($validator) use($input) {
            if ($input['password'] !== $input['password_again']) {
                $validator->errors()->add('password_again', '两次输入密码不一致');
            }
            if ($this->userService->isRegVerifyCodeExpired($input['mobile'])) {
                $validator->errors()->add('mobile.verifyCodeExpired', '验证码过期');
            }
            if (!$this->userService->isRegVerifyCodeValid($input['mobile'], $input['verifyCode'])) {
                $validator->errors()->add('mobile.verifyCodeInvalid', '验证码不正确');
            }
            $managedGroupsInfo = $this->userProfileHelper->getManagedGroups();

            if (!empty($managedGroupsInfo)) {
                $currentUserGroupId = $managedGroupsInfo['currentUserGroupId'];

                if (isset($input['group_id'])) {
                    $group = UserGroup::findOrFail($input['group_id']);
                    if ($group->coreOrganization()->id != $currentUserGroupId) {
                        $validator->errors()->add('group.illegal', '传入的用户组不合法');
                    }
                    $roles = $input['roleIds'];
                    if (!empty($roles)) {
                        $illegalRoles = $this->roleService->getGroupRoles($currentUserGroupId);

                        $isRoleIllegal = true;
                        $roleIds = explode(',', $roles);
                        foreach ($roleIds as $roleId) {
                            if (!empty($roleId)) {
                                $isRoleIllegal = $isRoleIllegal && in_array($roleId, $illegalRoles->pluck('id')->toArray());
                            }
                        }

                        if (!$isRoleIllegal) {
                            $validator->errors()->add('role.illegal', '传入的用户角色不合法');
                        }
                    } else {
                        $validator->errors()->add('role.required', '创建用户时需要至少指定一个角色');
                    }
                } else {
                    $validator->errors()->add('group.required', '用户没有所在用户组(部门或外部合作伙伴)信息');
                }
            } else {
                $validator->errors()->add('curgroup.required', '当前操作用户没有所在用户组(部门或外部合作伙伴)信息');
            }
        })->validate();
    }

    private function validateWhenSendVerifyCodeOnEdit(Array $input)
    {
        return Validator::make($input, [
            'mobile' => 'required|max:20|exists:users,mobile',
        ], [
            'mobile.required' => '没有输入手机号',
            'mobile.max' => '手机号长度不可超过:max',
            'mobile.exists' => '该手机号不存在',
        ])->after(function ($validator) use($input) {
            if ($this->userService->isModifyVerifyCodeTooFrequency($input['mobile'])) {
                $validator->errors()->add('id', '验证码发送过于频繁');
            }
        })->validate();
    }

    private function validateWhenSendVerifyCode(Array $input)
    {
        return Validator::make($input, [
            'mobile' => 'required|max:20|unique:users,mobile',
        ], [
            'mobile.required' => '没有输入手机号',
            'mobile.max' => '手机号长度不可超过:max',
            'mobile.unique' => '该手机号已被注册',
        ])->after(function ($validator) use($input) {
            if ($this->userService->isRegVerifyCodeTooFrequency($input['mobile'])) {
                $validator->errors()->add('id', '验证码发送过于频繁');
            }
        })->validate();
    }

    private function validateUserMobileQuery(Array $input)
    {
        return Validator::make($input, [
            'mobile' => 'required|max:20',
            'groupId' => 'required|exists:user_groups,id',
        ], [
            'mobile.required' => '必须输入手机号',
            'mobile.max' => '手机号长度不可超过:max',
            'groupId.required' => '必须传入用户组ID',
            'groupId.exists' => '传入的用户组不存在',
        ])->after(function ($validator) use($input) {
            if ($this->userService->isUserWithMobileExistsInSameGroup($input['mobile'], $input['groupId'])) {
                $validator->errors()->add('id', '该用户已存在并且已经属于该组织');
            }
        })->validate();
    }

    private function validateCanQuery(Array $input)
    {
        return Validator::make($input, [
            'deptId' => [
                'required',
                Rule::in(UserGroup::whereIn('group_type', [
                    UserGroup::$GROUP_TYPE_INTERNAL_ORGANIZATION,
                    UserGroup::$GROUP_TYPE_INTERNAL_DEPARTMENT
                ])->get()->pluck('id')->toArray())
            ]
        ], [
            'deptId.required' => '查询条件里必须有部门id',
            'deptId.in' => '部门id格式不合法'
        ])->validate();
    }
}
